const app = getApp()

Page({
  data: {

  },
  onLoad() {
    console.log('代码片段是一种迷你、可分享的小程序或小游戏项目，可用于分享小程序和小游戏的开发经验、展示组件和 API 的使用、复现开发问题和 Bug 等。可点击以下链接查看代码片段的详细文档：')
    console.log('https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/devtools.html')
    let that = this;
    that.initDrag();
  },

  /**
   * x,y 方向同时可以移动
   */

  /**
   * 初始化渲染
   */
  initDrag: function () {
    let that = this;

    // 获取屏幕宽度
    wx.getSystemInfoAsync({
      success(res) {
        let getwindowWidth = res.screenWidth
        let columns = 4; //分几列
        let movableview_width = Math.round((getwindowWidth / columns), 2);
        // 跟页面样式 movableview 高度相同：60(每个直接紧紧相靠，如果要有上下间距，就 + 一个数子)，样式改了，记得这里要改，单位用px
        let movableview_height = 60 + 10;

        // 可拖动模块列表
        let arr = [{
            dragItem: '1'
          },
          {
            dragItem: '2'
          },
          {
            dragItem: '3'
          },
          {
            dragItem: '4'
          },
          {
            dragItem: '5'
          }, {
            dragItem: '6'
          },
          {
            dragItem: '7'
          },
          {
            dragItem: '8'
          },
          {
            dragItem: '9'
          },
          {
            dragItem: '10'
          }, {
            dragItem: '11'
          },
          {
            dragItem: '12'
          },
          {
            dragItem: '13'
          },
          {
            dragItem: '14'
          },
          {
            dragItem: '15'
          },
          {
            dragItem: '16'
          },
          {
            dragItem: '17'
          },
        ]

        // 批量给坐标
        // movable-view 组件是通过 x，y 属性进行定位，所以算出每个的 x，y 值即可正确渲染
        arr = that.setCoordinate(arr, columns, movableview_width, movableview_height);

        // movable-view的y值单位是px
        that.setData({
          arr,
          // 元素尺寸
          getwindowWidth,
          columns,
          movableview_width,
          movableview_height,
        })
      },
    });
  },

  /**
   * 正整数正则
   */
  checkIsIntNumber: function (dragItem) {
    let re = /^[1-9]\d*$/; //判断字符串是否为数字
    if (!re.test(dragItem)) {
      return false;
    } else {
      return true;
    };
  },

  /**
   * 点击时
   */
  tap: function () {
    // console.log('在拖拽时是否出发点击行为？')  // 在拖拽时不触发点击行为
  },

  /**
   * 拖动开始
   */
  drag_movable_view_change: function (e) {
    // 这个函数是坐标变化就执行，所以可以用来做，移动到某个元素的区域，这个元素的样式加个灰色阴影
    this.y = e.detail.y;
    this.x = e.detail.x;
    // let dragId = e.currentTarget.id;
    // let dragStartId = e.currentTarget.dataset.index
    // 默认item id，wx-for 分配给每个item的index，我在html里id={{index}}，即用id变量记录分配后的index
    this.setData({
      // dragStartId,
      // dragStartEndX: this.x,
      // dragStartEndY: this.y,
      flag: true,
    });
  },

  /**
   * 监听滚动
   */
  onPageScroll: function (e) {
    this.data.scrollTop = e.scrollTop;
  },

  /**
   * 拖动结束
   * 实现原理：
   * 1.拖动完成时，替换拖动项目的坐标为放手时坐标
   * 2.给数组按坐标排序，用冒泡算法排序
   * 3.重新给每个元素坐标（x,y）（每行3个的算法已经实现）
   */
  drag_movable_view_end: function (e) {
    let that = this;
    if (!that.data.flag) {
      // 非长按情况下
      return;
    }

    // 1. 修改拖动项目的坐标为放手时坐标
    let index = e.currentTarget.dataset.index; // 正在拖动元素的序号

    let arr = that.data.arr; //原数组
    let columns = that.data.columns;
    let movableview_width = that.data.movableview_width;
    let movableview_height = that.data.movableview_height;

    // 获取拖动放手时的坐标,拖了遮住一半左右距离就可以，所以强制加一半距离
    let dragItemEndX = that.x + (movableview_width / 2); // 放手时拖动项目的X坐标的值是 item 左边线到 movearea 左边的距离+一半项目宽度
    let dragItemEndY = that.y + (movableview_height / 2); // 放手时拖动项目的Y坐标的值是 item 上边线到 movearea 顶端的距离+一半项目高度

    // 用新坐标改原来的坐标 
    arr[index].x = dragItemEndX;
    arr[index].y = dragItemEndY;


    //2. 冒泡排序数组
    // 给误差或让拖动精确，也就是让拖动更自然，在两两元素比较函数里，控制精细程度，也就是移动多少算移动，也就是交换位置
    // 待处理，下一行往上一行拖时，不超过上一行的上边，它就不会到上一行
    let afterSortArr = that.SetSortPoint(arr);

    // 3. 按数组索引顺序重新给页面坐标
    arr = that.setCoordinate(arr, columns, movableview_width, movableview_height);

    // 4. 渲染到页面
    that.setData({
      arr: afterSortArr,
      flag: false,
    })
  },


  // 冒泡排序，对所有点用坐标进行排序
  SetSortPoint: function (arry) {
    let that = this;
    let len = arry.length;
    // x,y两个都要比较，所以就两层循环
    for (let i = 0; i < len - 1; i++) {
      for (let j = 0; j < len - 1 - i; j++) {
        // 两个点进行比较
        if (that.SetSortRule(arry[j], arry[j + 1])) {
          let tmp = arry[j];
          arry[j] = arry[j + 1];
          arry[j + 1] = tmp;
        };
      };
    };

    return arry;
  },

  //两个坐标比较大小，x,y
  SetSortRule: function (p1, p2) {
    let that = this;

    // 误差忽略，跨行移动，需要大于两行的间距
    if (p1.y > p2.y && (p1.y - p2.y) > that.data.movableview_height) {
      // 跨行拖，一定要交换顺序，直到本行全部交换完毕
      return true;
    } else if (p1.y > p2.y && (p1.y - p2.y) < that.data.movableview_height) {
      // 没有跨行拖，或跨行拖的已经排序到最终这一行，只等判断x进行交互位置
      return (p1.x >= p2.x);
    } else if (p1.y == p2.y) {
      return (p1.x > p2.x);
    } else {
      return false;
    };
  },


  /**
   * 批量给坐标
   */
  setCoordinate: function (arr, columns, movableview_width, movableview_height) {
    let that = this;
    // 批量给坐标
    // movable-view 组件是通过 x，y 属性进行定位，所以算出每个的 x，y 值即可正确渲染
    let j = 0;
    for (let i in arr) {
      if (columns == 1) {
        // 分析：如果每行1个换行，也就是每1个 y 坐标就要增加了，引入 j 变量 是为了写法与下面对齐
        // i = 0,1,2,3,4,5,6...
        // j = 0,1,2,3,4,5,6...
        j = j + 1;
      };
      if (columns == 2) {
        // 分析：如果每行2个换行，也就是每2个，y坐标的值是不变的，这里用j变量代替y，只要实现每2个后j+1
        // i = 0,1,  2,3,  4,5,  6,7,  8...
        // j = 0,0,  1,1,  2,2,  3,3,  4...
        // 要想每行3个，然后换行，X 坐标，每3个就要，返回执行0，1，2，计算公式就是 i - 3 * j

        //i 循环 0，1 这 2 个时 j 都不 +1，原理是用除2取余数
        if (i > 0 && i % 2 == 0) {
          j = j + 1;
        }

      };
      if (columns == 3) {
        // 分析：如果每行3个换行，也就是每3个，y坐标的值是不变的，这里用j变量代替y，只要实现每3个后j+1
        // i = 0,1,2,  3,4,5,  6,7,8,  9...
        // j = 0,0,0,  1,1,1,  2,2,2,  3...
        // 要想每行3个，然后换行，X 坐标，每3个就要，返回执行0，1，2，计算公式就是 i - 3 * j

        //i 循环 0，1，2 这 3 个时 j 都不 +1，原理是用除3取余数
        if (i > 0 && i % 3 == 0) {
          j = j + 1;
        }

      };
      if (columns == 4) {
        // 分析：如果每行4个换行，也就是每4个，y坐标的值是不变的，这里用j变量代替y，只要实现每4个后j+1
        // i = 0,1,2,3, 4,5,6,7, 8,9
        // j = 0,0,0,0, 1,1,1,1 ,2,2
        // 要想每行4个，然后换行，X 坐标，每4个就要，返回执行0，1，2，3，计算公式就是 i - 4 * j

        //i 循环 0，1，2 这 3 个时 j 都不 +1，原理是当 i除以4的结果是大于 0 的整整数时才 +1 
        if (that.checkIsIntNumber(i / 4)) {
          j = j + 1;
        };
      };

      arr[i].x = (i - columns * j) * movableview_width;
      arr[i].y = j * movableview_height;
    };
    return arr;
  },
  // 可拖动组件结束
})